home *** CD-ROM | disk | FTP | other *** search
-
- /****************************************************************************/
- /* */
- /* Application: Out of This GWorld */
- /* */
- /* Description: This application demonstrates one method to */
- /* produce animation on the Macintosh using QuickDraw's */
- /* palette manager animation routines. The app simply */
- /* creates an offscreen image, copies it to the */
- /* screen's window, then calls AnimatePalette() */
- /* every cycle through the eventloop. To provide the */
- /* fastest possible animation, the image is only */
- /* created and copied once from the offscreen GWorld. */
- /* The actual animation is produced by shifting the */
- /* color entries within its colortable forward or */
- /* backward one index. Also the cTable is divided */
- /* and shifted in two separate groups to simulate */
- /* objects moving at different speeds. */
- /* */
- /* Files: out.c - offscreen and color routines */
- /* draw.c - custom drawing routines */
- /* events.c - standard event handling routines */
- /* menu.c - standard menu bar routines */
- /* */
- /* Programmer: Edgar Lee */
- /* Organization: Apple Computer, Inc. */
- /* Department: Developer Technical Support, DTS */
- /* Language: C (Think C version 4.0.4) */
- /* Date Created: 8-13-91 */
- /* */
- /****************************************************************************/
-
- #include "out.h"
-
- /*******************************/
- /* Global Variable Definitions */
- /*******************************/
-
- WindowPtr gWindow; /* Main Display Window */
- CTabHandle gCTable; /* Window & offscreen Colortable */
- GWorldPtr gGWorld; /* Offscreen GWorld */
- PixMapHandle gPixMap; /* PixMap of the GWorld */
- PaletteHandle gPalette; /* Window & offscreen Palette */
-
- int gCurrentPat = 1; /* Current Test Pattern */
- int gCurrentMove = STOP; /* Current State of Animation */
- int gCurrentDir = FORWARD; /* Current Direction to Shift Palette Colors */
- int gCurrentColor = COLOR; /* Current Colors: mixed or gray */
-
- main()
- {
- MaxApplZone(); /* Increase application heap. */
-
- initMac(); /* Do standard mac initializations. */
- initVariables(); /* Initialize the colortable. */
-
- createWindow();
- createPalette();
- createGWorld();
-
- createImage(); /* Create the current image offscreen. */
- drawImage(); /* Copybits the offscreen image into the window. */
-
- pollEvents(); /* Handle any events & update the palette. */
- }
-
- void initMac()
- {
- /*********************************/
- /* Standard Initialization Calls */
- /*********************************/
-
- InitGraf( &thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
- InitCursor();
- FlushEvents( 0, everyEvent );
-
- setUpMenus();
- }
-
- void initVariables()
- {
- /********************************************************************/
- /* Allocate memory for the colortable. Since ColorTable already */
- /* contains one ColorSpec, allocate (TOTALCOLORS - 1) ColorSpec's. */
- /* One ColorSpec is required for each entry. */
- /********************************************************************/
-
- gCTable = (CTabHandle)NewHandle( sizeof( ColorTable ) +
- ((TOTALCOLORS - 1) * sizeof( ColorSpec )));
- }
-
- void createWindow()
- {
- Rect wBounds;
-
- /*****************************************************************/
- /* Create and center the destination window in the main monitor. */
- /*****************************************************************/
-
- SetRect( &wBounds, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
- gWindow = NewCWindow( 0L, &wBounds, "\pOut of This GWorld", true, noGrowDocProc,
- (WindowPtr)-1L, true, 0L );
-
- /**************************************************************/
- /* Display the main window and assign it as the current port. */
- /**************************************************************/
-
- ShowWindow( gWindow );
- SetPort( gWindow );
- }
-
- void createPalette()
- {
- /********************************************************************/
- /* Allocate a palette for color animation. Using pmExplicit as the */
- /* usage, tells QD that the index values in the palette are more */
- /* important than the rgb values stored at that index. This is */
- /* necessary since the animation in this application is simulated */
- /* by shifting the colors at each palette index. */
- /********************************************************************/
-
- gPalette = NewPalette( TOTALCOLORS, nil, pmAnimated + pmExplicit, 0 );
-
- /************************************************/
- /* Define the rgb values at each palette index. */
- /************************************************/
-
- defineColorPalette();
-
- /******************************************/
- /* Attach the palette to the main window. */
- /******************************************/
-
- SetPalette( gWindow, gPalette, true );
- }
-
- void createGWorld()
- {
- int i;
- Rect gBounds;
- CGrafPtr currentPort;
- GDHandle currentDevice;
-
- /*************************************************/
- /* Define the size of the GWorld's bounding box. */
- /*************************************************/
-
- SetRect( &gBounds, 0, 0, gWindow->portRect.right - gWindow->portRect.left,
- gWindow->portRect.bottom - gWindow->portRect.top );
-
- /********************************************************************************/
- /* Convert the palette to a colortable before explicitly setting bit 14 in */
- /* the ctFlags field of the colortable. This tells the colortable to refer */
- /* to the palette indexes instead of its rgb values. Again, this is */
- /* necessary since the animation is performed by altering the palette. */
- /********************************************************************************/
-
- Palette2CTab( gPalette, gCTable );
- (**gCTable).ctFlags |= 0x4000;
-
- /************************************************************************/
- /* Make sure each value field of the colortable is assigned to the */
- /* corresponding entry in the palette and make sure the ctSeed field */
- /* is given a unique value. */
- /************************************************************************/
-
- for (i = 0; i < TOTALCOLORS; i++)
- (**gCTable).ctTable[i].value = i;
- (**gCTable).ctSeed = GetCTSeed();
-
- /*************************************************************************/
- /* Allocate a new GWorld for the offscreen drawing and store its PixMap. */
- /*************************************************************************/
-
- NewGWorld( &gGWorld, 8, &gBounds, gCTable, nil, 0 );
- gPixMap = GetGWorldPixMap( gGWorld );
- }
-
- void updatePalette()
- {
- /******************************************************************************/
- /* Convert the altered colortable to a palette, then animate all its entries. */
- /******************************************************************************/
-
- Palette2CTab( gPalette, gCTable );
- AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS );
- }
-
- void defineColorPalette()
- {
- int i;
-
- gCurrentColor = COLOR;
-
- /***********************************************************************/
- /* Define the first 8 palette entries with primary & secondary colors. */
- /***********************************************************************/
-
- setRGB( 0, 0, 0, 0 ); /* black */
- setRGB( 1, 0, 255, 0 ); /* green */
- setRGB( 2, 0, 255, 255 ); /* cyan */
- setRGB( 3, 0, 0, 255 ); /* blue */
- setRGB( 4, 255, 0, 255 ); /* magenta */
- setRGB( 5, 255, 0, 0 ); /* red */
- setRGB( 6, 255, 255, 0 ); /* yellow */
- setRGB( 7, 255, 255, 255 ); /* white */
-
- /*******************************************************************/
- /* Define shades of the previous colors for the remaining entries. */
- /*******************************************************************/
-
- for (i = 8; i < 48; i++) /* greens */
- setRGB( i, 0, 10 + ((i - 8) * 6), 0 );
-
- for (i = 48; i < 88; i++) /* blues */
- setRGB( i, 0, 0, 10 + ((i - 48) * 6) );
-
- for (i = 88; i < 128; i++) /* reds */
- setRGB( i, 10 + ((i - 88) * 6), 0, 0 );
-
- for (i = 128; i < 168; i++) /* magentas */
- setRGB( i, 10 + ((i - 128) * 6), 0, 10 + ((i - 128) * 6) );
-
- for (i = 168; i < 208; i++) /* yellows */
- setRGB( i, 10 + ((i - 168) * 6), 10 + ((i - 168) * 6), 0 );
-
- for (i = 208; i < 248; i++) /* cyans */
- setRGB( i, 0, 10 + ((i - 208) * 6), ((i - 208) * 6) );
- }
-
- void defineGrayPalette()
- {
- int i;
- int shade;
-
- gCurrentColor = GRAY;
-
- /*******************************************************/
- /* Define all the palette entries with shades of gray. */
- /*******************************************************/
-
- for (i = 1; i < 7; i++)
- {
- shade = i * 42;
- setRGB( i, shade, shade, shade );
- }
-
- for (i = 8, shade = 10; i < 248; i++)
- {
- setRGB( i, shade, shade, shade );
- shade += 12;
-
- if ((i - 8) % 20 == 0)
- shade = 10;
- }
- }
-
- void setRGB( index, r, g, b )
- int index;
- int r, g, b;
- {
- RGBColor aColor;
-
- /***********************************************************************/
- /* Set the rgb values for the palette color stored at the index value. */
- /***********************************************************************/
-
- aColor.red = r * SUN2MAC; /* All colors were defined using */
- aColor.green = g * SUN2MAC; /* SUN computer raster values. */
- aColor.blue = b * SUN2MAC;
-
- SetEntryColor( gPalette, index, &aColor );
- }
-
- void setColor( index )
- int index;
- {
- RGBColor aColor;
-
- /********************************************************/
- /* Get the rgb values stored at the index value in the */
- /* palette, then use it as the foreground color. */
- /********************************************************/
-
- GetEntryColor( gPalette, index, &aColor );
- RGBForeColor( &aColor );
- }
-
- void createImage()
- {
- CGrafPtr currentPort;
- GDHandle currentDevice;
- RGBColor aColor;
-
- /******************************************************************************/
- /* Store the current port and device before switching to the offscreen world. */
- /******************************************************************************/
-
- GetGWorld( ¤tPort, ¤tDevice );
-
- /****************************************************************************/
- /* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
- /****************************************************************************/
-
- SetGWorld( gGWorld, nil );
- LockPixels( gPixMap );
-
- /************************************************/
- /* Set the background color to black then erase */
- /* the PixMap's bounding box in the GWorld. */
- /************************************************/
-
- GetEntryColor( gPalette, 0, &aColor );
- RGBBackColor( &aColor );
- EraseRect( &(**gPixMap).bounds );
-
- /*************************************************************/
- /* Draw a 1 pixel wide white border along the PixMap's edge. */
- /*************************************************************/
-
- drawWindowBorder();
-
- /*************************************************************************/
- /* Depending on the current test pattern, create an image in the PixMap. */
- /*************************************************************************/
-
- if (gCurrentPat == 1)
- createColorScale();
- else if (gCurrentPat == 2)
- createColorWheels();
- else if (gCurrentPat == 3)
- createColorRings();
- else if (gCurrentPat == 4)
- createColorGears();
- else if (gCurrentPat == 5)
- createColorCurves();
- else if (gCurrentPat == 6)
- createColorBalls();
- else if (gCurrentPat == 7)
- createColorWave();
- else if (gCurrentPat == 8)
- createColorText();
- else
- doAbout(); /* Treat the About message as a test pattern. */
-
- /********************************************************************/
- /* After drawing the image, unlock the offscreen buffer in memory */
- /* and set the port and device back to the window's. */
- /********************************************************************/
-
- UnlockPixels( gPixMap );
- SetGWorld( currentPort, currentDevice );
- }
-
- void drawWindowBorder()
- {
- /********************************************************************/
- /* Set the foreground color to white before drawing a 1 pixel wide */
- /* frame around the PixMap's bounding box. */
- /********************************************************************/
-
- setColor( 7 );
- PenSize( 1, 1 );
- MoveTo( 0, 0 );
- LineTo( 0, (**gPixMap).bounds.bottom - 1 );
- LineTo( (**gPixMap).bounds.right - 1, (**gPixMap).bounds.bottom - 1 );
- LineTo( (**gPixMap).bounds.right - 1, 0 );
- }
-
- void drawImage()
- {
- /***********************************************************/
- /* Transfer the contents of the PixMap to the main window. */
- /***********************************************************/
-
- CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &(**gPixMap).bounds,
- &gWindow->portRect, srcCopy, 0l);
- }
-
- void animateCTable()
- {
- static int counter = 0;
- RGBColor aColor;
-
- /**************************************************************************/
- /* Convert the Palette to a colortable before shifting the color entries. */
- /**************************************************************************/
-
- Palette2CTab( gPalette, gCTable );
-
- /************************************************************************/
- /* Depending on the current direction, shift 239 palette entries either */
- /* ahead 1 or behind 1 index. Store the first or last entry before */
- /* shifting to avoid overwriting its rgb values. */
- /************************************************************************/
-
- if (gCurrentDir == FORWARD)
- {
- aColor = (**gCTable).ctTable[247].rgb;
- BlockMove( &(**gCTable).ctTable[8].value, &(**gCTable).ctTable[9].value,
- 239 * sizeof(ColorSpec) );
- (**gCTable).ctTable[8].rgb = aColor;
- }
- else
- {
- aColor = (**gCTable).ctTable[8].rgb;
- BlockMove( &(**gCTable).ctTable[9].value, &(**gCTable).ctTable[8].value,
- 239 * sizeof(ColorSpec) );
- (**gCTable).ctTable[247].rgb = aColor;
- }
-
- /**************************************************************/
- /* Shift the first 5 colortable entries once every 6 updates. */
- /**************************************************************/
-
- if (counter == 0)
- {
- aColor = (**gCTable).ctTable[1].rgb;
- BlockMove( &(**gCTable).ctTable[2].value, &(**gCTable).ctTable[1].value,
- 5 * sizeof(ColorSpec) );
- (**gCTable).ctTable[6].rgb = aColor;
- }
-
- /********************************************************/
- /* Update the window's colors by passing the new */
- /* colortable as the srcCTab field of AnimatePalette. */
- /********************************************************/
-
- AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS );
-
- /**********************************************/
- /* Increment the counter by 1 on each update. */
- /**********************************************/
-
- counter = (counter + 1) % 6;
- }
-
- void doAbout()
- {
- Rect rect;
- PicHandle thePict;
- int width, height;
-
- /*******************************************************/
- /* Load the About picture stored in the resource fork. */
- /*******************************************************/
-
- thePict = (PicHandle)GetResource( 'PICT', 128 );
-
- /************************************************/
- /* Define the rect used to enclose the picture. */
- /************************************************/
-
- width = (**thePict).picFrame.right - (**thePict).picFrame.left;
- height = (**thePict).picFrame.bottom - (**thePict).picFrame.top;
-
- SetRect( &rect, (WWIDTH - width) / 2, (WHEIGHT - height) / 2,
- ((WWIDTH - width) / 2) + width, ((WHEIGHT - height) / 2 ) + height );
-
- /*********************************/
- /* Draw the picture in the rect. */
- /*********************************/
-
- DrawPicture( thePict, &rect );
- ReleaseResource( thePict );
- }
-
- void cleanUp()
- {
- /*****************************************************************************/
- /* Free the memory set aside for the GWorld and main window before exitting. */
- /*****************************************************************************/
-
- DisposeGWorld( gGWorld );
- DisposeWindow( gWindow );
- ExitToShell();
- }